#include <fcntl.h>
#include <termios.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#include "contr_suite.h"

#define BAUDRATE B115200
#define MODEMDEVICE "/dev/ttyUSB0"
#define _POSIX_SOURCE 1 /* POSIX compliant source */

static void setTio(int fd) {
    struct termios newtio;

    bzero(&newtio, sizeof(newtio));
    newtio.c_cflag = BAUDRATE | CS8 | CLOCAL | CREAD;
    newtio.c_iflag = IGNPAR | IGNCR;
    newtio.c_oflag = 0;

    /* set input mode (non-canonical, no echo,...) */
    newtio.c_lflag = 0;

    newtio.c_cc[VTIME]    = 1;   /* inter-character timer used. 1/10th of second */
    newtio.c_cc[VMIN]     = 0;   /* blocking read until 0 chars received */

    tcflush(fd, TCIFLUSH);
    tcsetattr(fd, TCSANOW, &newtio);
}

int openFile() {
    int fd = open(MODEMDEVICE, O_RDWR | O_NOCTTY ); 
    if (fd < 0) {
        perror(MODEMDEVICE);
        exit(1);
    }
    setTio(fd);
    return fd;
}

int transferMessage(int in_fd, int out_fd) {
    char prev_c;
    char c;
    int count = 0;

    prev_c = 0;
    while (1) {
        int readCount;
        do {
            readCount = read(in_fd, &c, 1);
        } while (readCount < 0 && (errno == EAGAIN || errno == EINTR));
        if (readCount <= 0)
            break;
        int writeCount;
        do {
            writeCount = write(out_fd, &c, 1);
        } while (writeCount < 0 && (errno == EAGAIN || errno == EINTR));
        if (writeCount <= 0)
            break;
        count++;
        if (c == 10 && prev_c == 10)
            break;
        prev_c = c;
    }
    return count;
}

int getMessage(int fd, char *buf, int bufsize) {
    int len = 0;
    char prev_c;
    char c;
    int index = 0;

    prev_c = 0;
    while (index < bufsize - 1) {
        int readCount;
        do {
            readCount = read(fd, &c, 1);
        } while (readCount < 0 && (errno == EAGAIN || errno == EINTR));
        if (readCount <= 0)
            break;
        buf[index++] = c;
        if (c == 10 && prev_c == 10)
            break;
        prev_c = c;
    }
    buf[index] = 0;
    len = index;
    return len;
}

int sendMessage(char *buf, int fd) {
    int len = strlen(buf);
    int writtenCount = 0;
    int prevWritten;
    do {
        prevWritten = write(fd, buf + writtenCount, len - writtenCount);
        if (prevWritten > 0)
            writtenCount += prevWritten;
    } while (prevWritten < 0 && (errno == EAGAIN || errno == EINTR));
    if (prevWritten < 0)
        return writtenCount;
    if (len < 1 || buf[len - 1] != 10) {
        prevWritten = write(fd, "\n\n", 2);
        if (prevWritten > 0)
            writtenCount += prevWritten;
    } else if (len < 2 || buf[len - 2] != 10) {
        prevWritten = write(fd, "\n", 1);
        if (prevWritten > 0)
            writtenCount += prevWritten;
    }
    return writtenCount;
}
